package com.gmail.rusal4ica.logic;

/**
 * @author The Imperial Sword Team
 */

public class DotsGame implements Playable {
	private static final int NUM_SIDES_BOX = 4;
	
	public static final String PLAYER_ONE_NAME = "Player 1";
	public static final String PLAYER_TWO_NAME = "Player 2";

	public static final char PLAYER_ONE_SIGN = 'X';
	public static final char PLAYER_TWO_SIGN = 'O';

	private Player player1;
	private Player player2; 

	private Board dotsBoard;

	public DotsGame(){}

	public DotsGame(int sizeN, int sizeM){
		dotsBoard = new Board(sizeN, sizeM);
		player1 = new Player(PLAYER_ONE_NAME, PLAYER_ONE_SIGN);
		player2 = new Player(PLAYER_TWO_NAME, PLAYER_TWO_SIGN);
		Player.setCurrentPlayer(player1);
	}

	/**
	 * The method is used for playing the game.
	 */
	public void playDotsGame(int i, int j){
		recordMove(i, j);	
	}

	public void switchIfNeeded(int i, int j) {
		if(!isLineClosingBox (dotsBoard.getBoard(), i, j)){
			Player.switchPlayers(player1, player2);
		}
	}
	
	/**
	 * The method checks if the game is over.
	 * 
	 * @return - true or false
	 */
	public boolean isGameOver(){
		for (int i = 0; i < dotsBoard.getBoardSizeN(); i++) {
			for (int j = 0; j < dotsBoard.getBoardSizeM(); j++) {
				if(dotsBoard.getBoardCharAt(i, j) == Board.LINE_FIELD_DEFAULT){
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * The method checks if the player closed a field within this turn.
	 * 
	 * @param array - the game board
	 * @param i - row
	 * @param j - column
	 * @return - true or false
	 */
	public boolean isLineClosingBox(char[][] array, int i, int j){
		boolean fieldOne = false;
		boolean fieldTwo = false;

		if(array[i][j] == Board.LINE_FIELD_HORIZONTAL){
			if((i - 1 >= 0)&& (array[i - 1][j] == Board.FIELD_EMPTY)){
				fieldOne = isBoxClosed(array,i - 1, j);
				if(fieldOne){			
					array[i - 1][j] = Player.getCurrentPlayer().getSign();
					Player.getCurrentPlayer().addResult();
				}
			}

			if((i + 1 < array.length) && (array[i + 1][j] == Board.FIELD_EMPTY)){
				fieldTwo = isBoxClosed(array,i + 1, j );
				if(fieldTwo){
					array[i + 1][j] = Player.getCurrentPlayer().getSign();
					Player.getCurrentPlayer().addResult();
				}
			}

			if(fieldOne || fieldTwo){
				return true;
			} else {
				return false;
			}
		}

		if(array[i][j] == Board.LINE_FIELD_VERTICAL){
			if((j - 1 >= 0)&& (array[i][j - 1] == Board.FIELD_EMPTY)){
				fieldOne = isBoxClosed(array,i, j - 1);
				if(fieldOne){
					array[i][j - 1] = Player.getCurrentPlayer().getSign();
					Player.getCurrentPlayer().addResult();
				}
			}

			if((j + 1 < array[0].length)&& (array[i][j + 1] == Board.FIELD_EMPTY)){
				fieldTwo = isBoxClosed(array,i, j + 1);
				if(fieldTwo){
					array[i][j + 1] = Player.getCurrentPlayer().getSign();
					Player.getCurrentPlayer().addResult();
				}
			}
			if(fieldOne || fieldTwo){
				return true;
			} else {
				return false;
			}
		}
		return false;
	}

	/**
	 * The method checks if this line closes the box
	 *  
	 * @param array - the game board
	 * @param i - row coordinate
	 * @param j - column coordinate
	 * @return - true or false
	 */
	private boolean isBoxClosed(char[][] array, int i, int j){
		int counter = 0;

		if((i - 1 >= 0) && (array[i - 1][j] != Board.LINE_FIELD_DEFAULT)){//top side
			counter++;
		}
		if((i + 1 < array.length) && (array[i + 1][j] != Board.LINE_FIELD_DEFAULT)){//bottom side
			counter++;
		}
		if((j - 1 >= 0) && (array[i][j - 1] != Board.LINE_FIELD_DEFAULT)){//left side
			counter++;
		}
		if((j + 1 < array[0].length) && (array[i][j + 1] != Board.LINE_FIELD_DEFAULT)){//right side
			counter++;
		}
		if(counter == NUM_SIDES_BOX){
			return true;
		}
		return false;
	}

	/**
	 * The method records the move.
	 * 
	 * @param i - row coordinate of the move
	 * @param j - column coordinate of the move
	 */
	private void recordMove(int i, int j){
		if(isLegalMove(i, j)){
			if(i % 2 == 0){
				dotsBoard.getBoard()[i][j] = Board.LINE_FIELD_HORIZONTAL;
			} else {
				dotsBoard.getBoard()[i][j] = Board.LINE_FIELD_VERTICAL;
			}
		}
	}

	/**
	 * The method checks if the move made by the player is legal.
	 * 
	 * @param i - row coordinate of the move
	 * @param j - column coordinate of the move
	 * @return - true or false
	 */
	private boolean isLegalMove(int i, int j) {
		return (dotsBoard.isRowIndexInRange(i) && dotsBoard.isColumnIndexInRange(j) && (dotsBoard.getBoard()[i][j] == Board.LINE_FIELD_DEFAULT));
	}

	public Board getDotsBoard() {
		return dotsBoard;
	}

	public Player theWinnerIs(){
		if(player1.getResult() > player2.getResult())
			return player1;
		if(player1.getResult() < player2.getResult())
			return player2;

		return new Player("Nobady", 'n');
	}

}
